home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’92 / FinderMenu ƒ / FinderMenu INIT ƒ / DrawstringHack.c next >
Encoding:
C/C++ Source or Header  |  1992-06-17  |  8.4 KB  |  414 lines  |  [TEXT/KAHL]

  1. /*
  2. /*
  3.  * (C) 1992 SixxHeads Software
  4.  * (C) 1992 Berkeley Systems Inc.
  5.  * 
  6.  * This code is freely distributable, but credit must be given in any
  7.  * derivative work.
  8.  *
  9.  * <Revision History>
  10.  *        05/21/92  smz  Created for support of color icon families
  11.  * <release 1.0>
  12.  *      06/16/92  smz  need to do a HandToHand with the icon, not detatchresource
  13.  */
  14.  
  15. #include "Utils.h"
  16. #include "DrawstringHack.h"
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <stddef.h>
  20. #include <OSUtils.h>
  21. #include <Memory.h>
  22.  
  23. /*
  24.  * Special drawstring hacks…
  25.  */
  26.  
  27. #define cDefaultID    129    // skull wih an 'x' through it!
  28.  
  29. static FileRecord prefsFile;
  30. static Boolean theColorQD;
  31.  
  32. typedef struct SmallFamily {
  33.     short    itsID;
  34.     Handle    itsicsPHandle;
  35.     Handle    itsics4Handle;
  36.     Handle    itsics8Handle;
  37.  
  38.     struct SmallFamily **itsNextFamily;
  39. } SmallFamily, **SmallFamilyHandle;
  40.  
  41. static SmallFamilyHandle theCachedSmallFamily;
  42. static SmallFamilyHandle theDefaultSmallFamily;
  43.  
  44. static SmallFamilyHandle DoLoad(short id)
  45. {
  46.     reg SmallFamilyHandle hFamily;
  47.     reg SmallFamily *pFamily;
  48.  
  49.     hFamily = (SmallFamilyHandle) NewHandleSys(sizeof(SmallFamily));
  50.     if (hFamily == nil)
  51.         return nil;
  52.  
  53.     HLock(hFamily);
  54.     pFamily = *hFamily;
  55.  
  56.     pFamily->itsID = id;
  57.     pFamily->itsNextFamily = nil;
  58.  
  59.     if ((pFamily->itsicsPHandle = GetResource('ics#', id)) == nil
  60.     || (HandToHand(&pFamily->itsicsPHandle) != noErr)) {
  61.         DisposeHandle(hFamily);
  62.         return nil;
  63.     }
  64.  
  65.     if ((pFamily->itsics4Handle = GetResource('ics4', id)) != nil)
  66.         if (HandToHand(&pFamily->itsics4Handle) != noErr)
  67.             pFamily->itsics4Handle = nil;
  68.  
  69.     if ((pFamily->itsics8Handle = GetResource('ics8', id)) != nil)
  70.         if (HandToHand(&pFamily->itsics8Handle) != noErr)
  71.             pFamily->itsics8Handle = nil;
  72.  
  73.     HUnlock(hFamily);
  74.  
  75.     return hFamily;
  76. }
  77.  
  78. Boolean InitPrefsFile()
  79. {
  80.     SysEnvRec environment;            // machine configuration.
  81.  
  82.     NewFileRecord("\pFinderMenu Prefs", 'fmci', 'FMPR', &prefsFile);
  83.     (void) OpenPrefsFile(&prefsFile);
  84.     ClosePrefsFile(&prefsFile);
  85.  
  86.     theCachedSmallFamily = nil;
  87.     theDefaultSmallFamily = DoLoad(cDefaultID);
  88.  
  89.     // find out what kind of machine this is.
  90.     SysEnvirons(curSysEnvVers, &environment);
  91.     theColorQD = (environment.hasColorQD);
  92.  
  93.     return theDefaultSmallFamily != nil;
  94. }
  95.  
  96. static void TrashCachedFamily()
  97. {
  98.     reg SmallFamilyHandle aFamily = theCachedSmallFamily;
  99.  
  100.     while (aFamily != nil) {
  101.         reg SmallFamily *pFamily = *aFamily;
  102.         reg SmallFamilyHandle nextFamily = pFamily->itsNextFamily;
  103.  
  104.         if (pFamily->itsicsPHandle)
  105.             DisposeHandle(pFamily->itsicsPHandle);
  106.         if (pFamily->itsics4Handle)
  107.             DisposeHandle(pFamily->itsics4Handle);
  108.         if (pFamily->itsics8Handle)
  109.             DisposeHandle(pFamily->itsics8Handle);
  110.  
  111.         DisposeHandle(aFamily);
  112.         aFamily = nextFamily;
  113.     }
  114.     theCachedSmallFamily = nil;
  115. }
  116.  
  117. static SmallFamilyHandle LoadSmallFamily(short id)
  118. {
  119.     reg SmallFamilyHandle hFamily;
  120.  
  121.     if (! OpenPrefsFile(&prefsFile))
  122.         return nil;
  123.  
  124.     hFamily = DoLoad(id);
  125.  
  126.     if (! ClosePrefsFile(&prefsFile)) {
  127. #ifdef DEBUG
  128.         DebugStr("\pcouldn't close prefs!");
  129. #endif
  130.     }
  131.  
  132.     return hFamily;
  133. }
  134.  
  135. static SmallFamilyHandle GetSmallFamily(short id)
  136. {
  137.     reg SmallFamilyHandle aFamily;
  138.  
  139.     if (PrefsFileChanged(&prefsFile))
  140.         TrashCachedFamily();
  141.  
  142.     aFamily = theCachedSmallFamily;
  143.  
  144.     while (aFamily != nil) {
  145.         reg SmallFamily *pFamily = *aFamily;
  146.         if (pFamily->itsID == id)
  147.             return aFamily;
  148.         aFamily = pFamily->itsNextFamily;
  149.     }
  150.  
  151.     // didn't find it, load it and cache it
  152.     aFamily = LoadSmallFamily(id);
  153.  
  154.     if (aFamily != nil) {
  155.         (**aFamily).itsNextFamily = theCachedSmallFamily;
  156.         theCachedSmallFamily = aFamily;
  157.     }
  158.  
  159.     return aFamily;
  160. }
  161.  
  162. static void GetSmallRect(Rect *aRect, Point loc)
  163. {
  164.     SetRect(aRect, 0, 0, 16, 16);
  165.     OffsetRect(aRect, loc.h, loc.v - 12);
  166. }
  167.  
  168. static void DrawBWIcon(SmallFamilyHandle aFamily, Point loc)
  169. {
  170.     BitMap source;
  171.     Handle icon = (**aFamily).itsicsPHandle;
  172.     GrafPtr curPort;
  173.     Rect dstRect;
  174.  
  175.     if (icon == nil) {
  176.         aFamily = theDefaultSmallFamily;
  177.         icon = (**aFamily).itsicsPHandle;
  178.         if (icon == nil)
  179.             return;    // bad news!
  180.     }
  181.  
  182.     GetPort(&curPort);
  183.  
  184.     HLock(icon);
  185.  
  186.     // prepare the source and destination bitmaps.
  187.     source.baseAddr = *icon + 32;                    // mask address.
  188.     source.rowBytes = 2;
  189.     SetRect(&source.bounds, 0, 0, 16, 16);
  190.  
  191.     GetSmallRect(&dstRect, loc);
  192.  
  193.     // transfer the mask.
  194.     CopyBits(&source, &curPort->portBits, &source.bounds, &dstRect, srcBic, nil);
  195.  
  196.     // and the icon.
  197.     source.baseAddr = *icon;
  198.     CopyBits(&source, &curPort->portBits, &source.bounds, &dstRect, srcOr, nil);
  199.  
  200.     HUnlock(icon);
  201. }
  202.  
  203. static void DrawColorIcon(SmallFamilyHandle aFamily, Point loc, short desiredDepth)
  204. {
  205.     Handle mask, icon;
  206.     CTabHandle clut;
  207.     PixMapHandle source;
  208.     BitMap maskBits;
  209.     long rowBytes;
  210.     Rect dstRect, bounds;
  211.     CGrafPtr curPort;                                    // the current port we created.
  212.     short depthUsed;
  213.     RGBColor saveFore, saveBack;
  214.     RGBColor aColor;
  215.  
  216.     if ((**aFamily).itsics4Handle == nil && (**aFamily).itsics8Handle == nil) {
  217.         if ((**aFamily).itsicsPHandle != nil)
  218.             DrawBWIcon(aFamily, loc);
  219.  
  220.         return;
  221.     }
  222.  
  223.     GetPort(&curPort);
  224.     SetRect(&bounds, 0, 0, 16, 16);
  225.     GetSmallRect(&dstRect, loc);
  226.  
  227.     saveFore = curPort->rgbFgColor;
  228.     saveBack = curPort->rgbBkColor;
  229.     aColor.red = 0;
  230.     aColor.green = 0;
  231.     aColor.blue = 0;
  232.     RGBForeColor(&aColor);
  233.     aColor.red = -1;
  234.     aColor.green = -1;
  235.     aColor.blue = -1;
  236.     RGBBackColor(&aColor);
  237.  
  238.     mask = (**aFamily).itsicsPHandle;
  239.     if (mask) {
  240.         HLock(mask);
  241.         maskBits.baseAddr = *mask + 32;
  242.         maskBits.rowBytes = 2;
  243.         maskBits.bounds = bounds;
  244.     }
  245.  
  246.     if (desiredDepth == 4) {
  247.         icon = (**aFamily).itsics4Handle;
  248.         depthUsed = 4;
  249.     } else {
  250.         icon = (**aFamily).itsics8Handle;
  251.         depthUsed = 8;
  252.     }
  253.  
  254.     if (icon == nil) {
  255.         if (desiredDepth == 4) {
  256.             icon = (**aFamily).itsics8Handle;
  257.             depthUsed = 8;
  258.         } else {
  259.             icon = (**aFamily).itsics4Handle;
  260.             depthUsed = 4;
  261.         }
  262.     }
  263.  
  264.     if (icon == nil)        // should never happen
  265.         goto exit;
  266.  
  267.     HLock(icon);
  268.  
  269.     // get color stuff
  270.     clut = GetCTable(depthUsed);    // can return nil!
  271.  
  272.     // create a pixmap to stick the icon bits into for screen blitting.
  273.     source = NewPixMap();
  274.     if (! source)
  275.         goto exit;
  276.  
  277.     if (depthUsed == 8)
  278.         rowBytes = 16;
  279.     else
  280.         rowBytes = 8;
  281.  
  282.     (**source).baseAddr = *icon;
  283.     (**source).rowBytes = ((short) rowBytes) | 0x8000;
  284.     (**source).bounds = bounds;
  285.     (**source).pixelType = 0;            // chunky model.
  286.     (**source).pixelSize = depthUsed;
  287.     (**source).cmpCount = 1;            // if in 32 bit mode this will be 3, so must change.
  288.     (**source).cmpSize = depthUsed;            // only chunky images used.
  289.     DisposCTable((**source).pmTable);    // dispose of default, uninitialized table.
  290.     (**source).pmTable = clut;
  291.  
  292.     // draw the actual color icon.
  293.     HLock((Handle) source);
  294.     CopyMask((BitMap*) *source, &maskBits, (BitMap*)&curPort->portPixMap, &bounds, &bounds, &dstRect);
  295.     HUnlock((Handle) source);
  296.  
  297.     // release everything we've allocated.
  298.     // note that we dispose these elsewhere, so we don't want DisposPixMap to do it for us
  299.     (**source).pmTable = nil;
  300.     (**source).baseAddr = nil;
  301.     DisposPixMap(source);
  302.  
  303. exit: // release the icon and clut.
  304.     RGBForeColor(&saveFore);
  305.     RGBBackColor(&saveBack);
  306.  
  307.     if (clut)
  308.         DisposCTable(clut);
  309.  
  310.     if (icon)
  311.         HUnlock(icon);
  312.  
  313.     if (mask)
  314.         HUnlock(mask);
  315. }
  316.  
  317. static void TryPlotFamily(SmallFamilyHandle aFamily, Point loc)
  318. {
  319.     short depth;
  320.     short rowBytes;
  321.  
  322.     if (theColorQD) {
  323.         depth = (**(**GetMainDevice()).gdPMap).pixelSize;
  324.         if (depth < 4)
  325.             depth = 1;
  326.         else if (depth > 8)
  327.             depth = 8;
  328.     } else
  329.         depth = 1;
  330.  
  331.     if (depth == 1)
  332.         DrawBWIcon(aFamily, loc);
  333.     else
  334.         DrawColorIcon(aFamily, loc, depth);
  335. }
  336.  
  337. static char *ScanFor(reg char c, reg char *p, reg short len)
  338. {
  339.     while (len--)
  340.         if (*p == c)
  341.             return p;
  342.         else
  343.             ++p;
  344.  
  345.     return nil;
  346. }
  347.  
  348. static short GetStringParm(Str255 s, reg short ixToken)
  349. {
  350.     Str255 tmp;
  351.     reg char *p = (char *) &s[1];
  352.     reg char *pEnd = p + s[0];
  353.  
  354.     tmp[0] = 0;
  355.  
  356.     // finds tokens in a:
  357.     // CODE(x, y, ...) manner
  358.  
  359.     p = ScanFor('(', p, pEnd - p);
  360.  
  361.     if (p == nil)
  362.         return 0;
  363.  
  364.     ++p;
  365.  
  366.     while (ixToken-- && p <= pEnd) {
  367.         p = ScanFor(',', p, pEnd - p);
  368.  
  369.         if (p == nil)
  370.             return 0;
  371.  
  372.         ++p;
  373.     }
  374.  
  375.     if (p <= pEnd) {
  376.         while (p <= pEnd) {
  377.             if (*p != ' ' && *p != '\t')
  378.                 if (*p == ',' || *p == ')')
  379.                     break;
  380.                 else
  381.                     pushchar(*p, tmp);
  382.             ++p;
  383.         }
  384.         return String2Short(tmp);
  385.     }
  386.     return 0;
  387. }
  388.  
  389.  
  390. Boolean IsSpecialString(Str255 s)
  391. {
  392.     return 'IFAM' == (long) (((long) s[1] << 24) | (long)  ((long)s[2] << 16) | (long) ((long)s[3] << 8) | (long) s[4]);
  393. }
  394.  
  395. void DrawSpecialString(Str255 s)
  396. {
  397.     Point pnLoc;
  398.     reg SmallFamilyHandle hFam;
  399.  
  400.     GetPen(&pnLoc);
  401.  
  402.     hFam = GetSmallFamily(GetStringParm(s, 0));
  403.  
  404.     if (hFam == nil)
  405.         hFam = theDefaultSmallFamily;
  406.  
  407.     TryPlotFamily(hFam, pnLoc);
  408. }
  409.  
  410. short SpecialStringWidth(Str255 s)
  411. {
  412.     return 16;    // width of a SICN
  413. }
  414.